# Resolver.py
#
# Copyright (c) 2006 Michael Hobbs
#
# This file is part of iTorrent.
#
# iTorrent is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# iTorrent is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with iTorrent; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


import threading
import socket


queue = []
lock = threading.Lock()
semaphore = threading.Semaphore(0)


def startResolverThread(rawServer):
	thread = threading.Thread(target=resolver, args=(rawServer,))
	thread.setDaemon(True)
	thread.start()
	return thread

def resolve(hostName, callback, *args, **kwargs):
	lock.acquire()
	try:
		queue.append((hostName, callback, args, kwargs))
		semaphore.release()
	finally:
		lock.release()
	# end try

def resolver(rawServer):
	# TODO: log any exceptions that are raised here
	while True:
		semaphore.acquire()
		lock.acquire()
		try:
			hostName, callback, args, kwargs = queue.pop(0)
		finally:
			lock.release()
		ipAddress = socket.gethostbyname(hostName)
		# We can't use lambda or a nested function here, because Python's closures
		# aren't perfect closures. That is, if we loop around again before the callback
		# is invoked, ipAddress will be overwritten and will cause problems.
		rawServer.external_add_task(callCallback, 0, (ipAddress, callback, args, kwargs))
	# end while

def callCallback(ipAddress, callback, args, kwargs):
	callback(ipAddress, *args, **kwargs)
